﻿#include "DAWorkFlowGraphicsScene.h"
// Qt
#include <QApplication>
#include <QMatrix>
#include <QKeyEvent>
#include <QDebug>
#include <QGraphicsSceneDragDropEvent>
#include <DAStandardGraphicsTextItem.h>
// workflow
#include "DAAbstractNode.h"
#include "DANodeMimeData.h"
#include "DANodeMetaData.h"
#include "DAMimeTypeFormatDefine.h"
#include "DAWorkFlowGraphicsScene.h"
#include "DAGraphicsResizeablePixmapItem.h"
// api
#include "DAAppCore.h"
#include "DAAppUI.h"
#include "DACommandInterface.h"
// cmd
#include "DACommandsOfWorkFlow.h"
//===================================================
// using DA namespace -- 禁止在头文件using!!
//===================================================

using namespace DA;

//===================================================
// DAWorkFlowGraphicsScene
//===================================================
DAWorkFlowGraphicsScene::DAWorkFlowGraphicsScene(QObject* parent)
    : DANodeGraphicsScene(parent), _backgroundPixmapItem(nullptr), m_addTextFlag(false), m_enableItemMoveWithBackground(false)
{
    m_currentFont = QApplication::font();
}

/**
 * @brief 添加一个背景图,如果多次调用，此函数返回的QGraphicsPixmapItem* 是一样的，也就是只会创建一个QGraphicsPixmapItem*
 * @param pixmap
 * @return
 */
DAGraphicsResizeablePixmapItem* DAWorkFlowGraphicsScene::setBackgroundPixmap(const QPixmap& pixmap)
{
    DACommandWorkFlowSceneAddBackgroundPixmap* cmd = new DACommandWorkFlowSceneAddBackgroundPixmap(this, pixmap);
    undoStack().push(cmd);
    return _backgroundPixmapItem;
}
/**
 * @brief 获取背景图item
 * @return 如果没有设置返回一个nullptr
 */
DAGraphicsResizeablePixmapItem* DAWorkFlowGraphicsScene::getBackgroundPixmapItem(bool autoCreate)
{
    if (autoCreate) {
        return ensureGetBackgroundPixmapItem();
    }
    return _backgroundPixmapItem;
}

/**
 * @brief 设置背景item，如果外部调用getBackgroundPixmapItem并删除，需要通过此函数把保存的item设置为null
 * @note 此函数不会对item执行additem操作，仅仅只是交由DAWorkFlowGraphicsScene保存
 * @param item
 */
void DAWorkFlowGraphicsScene::setBackgroundPixmapItem(DAGraphicsResizeablePixmapItem* item)
{
    _backgroundPixmapItem = item;
}

/**
 * @brief 设置是否插入文本框
 * @param f 文本框的字体，默认使用应用程序字体
 */
void DAWorkFlowGraphicsScene::startCreateTextItemByMouse()
{
    m_addTextFlag = true;
}
/**
 * @brief 停止插入文本框
 */
void DAWorkFlowGraphicsScene::stopCreateTextItemByMouse()
{
    m_addTextFlag = false;
}

/**
 * @brief 判断是否处于创建textitem模式
 * @return
 */
bool DAWorkFlowGraphicsScene::isCreatingTextItemByMouse() const
{
    return m_addTextFlag;
}

void DAWorkFlowGraphicsScene::setTextBold(bool on)
{
    m_currentFont.setBold(on);
}

void DAWorkFlowGraphicsScene::setTextItalic(bool on)
{
    m_currentFont.setItalic(on);
}

void DAWorkFlowGraphicsScene::setTextColor(const QColor& color)
{
    m_textColor = color;
}

void DAWorkFlowGraphicsScene::setTextFamily(const QString& family)
{
    m_currentFont.setFamily(family);
}

void DAWorkFlowGraphicsScene::setTextSize(const int size)
{
    m_currentFont.setPointSize(size);
}
/**
 * @brief 允许item跟随背景图移动
 * @param on
 */
void DAWorkFlowGraphicsScene::enableItemMoveWithBackground(bool on)
{
    m_enableItemMoveWithBackground = on;
}

/**
 * @brief DAWorkFlowGraphicsScene::isEnableItemMoveWithBackground
 * @return
 */
bool DAWorkFlowGraphicsScene::isEnableItemMoveWithBackground() const
{
    return m_enableItemMoveWithBackground;
}

DAGraphicsResizeablePixmapItem* DAWorkFlowGraphicsScene::ensureGetBackgroundPixmapItem()
{
    if (nullptr == _backgroundPixmapItem) {
        _backgroundPixmapItem = new DAGraphicsResizeablePixmapItem();
        _backgroundPixmapItem->setZValue(-9999);
#if DA_USE_QGRAPHICSOBJECT
        connect(_backgroundPixmapItem, &DAGraphicsResizeablePixmapItem::xChanged, this, &DAWorkFlowGraphicsScene::backgroundPixmapItemXChanged);
        connect(_backgroundPixmapItem, &DAGraphicsResizeablePixmapItem::yChanged, this, &DAWorkFlowGraphicsScene::backgroundPixmapItemYChanged);
        connect(_backgroundPixmapItem,
                &DAGraphicsResizeablePixmapItem::itemBodySizeChanged,
                this,
                &DAWorkFlowGraphicsScene::backgroundPixmapItemBodyItemBodySizeChanged);
#endif
        addItem(_backgroundPixmapItem);
#if DA_USE_QGRAPHICSOBJECT
        _backgroundPixmapItemLastPos = _backgroundPixmapItem->pos();
        _pixmapResizeLastPos         = _backgroundPixmapItem->pos();
#endif
    }
    return _backgroundPixmapItem;
}

void DAWorkFlowGraphicsScene::dragEnterEvent(QGraphicsSceneDragDropEvent* event)
{
    if (event->mimeData()->hasFormat(MIME_NODE_META_DATA)) {
        //说明有节点的meta数据拖入
        event->acceptProposedAction();
    } else {
        event->ignore();
    }
}

void DAWorkFlowGraphicsScene::dragMoveEvent(QGraphicsSceneDragDropEvent* event)
{
    event->acceptProposedAction();
}

void DAWorkFlowGraphicsScene::dragLeaveEvent(QGraphicsSceneDragDropEvent* event)
{
    event->acceptProposedAction();
}

void DAWorkFlowGraphicsScene::dropEvent(QGraphicsSceneDragDropEvent* event)
{
    if (event->mimeData()->hasFormat(MIME_NODE_META_DATA)) {
        //说明有节点的meta数据拖入
        const DANodeMimeData* nodemime = qobject_cast< const DANodeMimeData* >(event->mimeData());
        if (nullptr == nodemime) {
            return;
        }
        clearSelection();
        DANodeMetaData nodemeta = nodemime->getNodeMetaData();
        createNode_(nodemeta, event->scenePos());
    }
}

void DAWorkFlowGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
{
    QPointF pos = mouseEvent->scenePos();
    if (isCreatingTextItemByMouse()) {
        stopCreateTextItemByMouse();

        DAStandardGraphicsTextItem* item = createText_();
        item->setPos(pos);
        item->setFont(m_currentFont);
        item->setDefaultTextColor(m_textColor);
        item->setEditMode(true);
        mouseEvent->accept();  //接受事件，通知下面的mousePressEvent函数事件已经接收，无需执行动作
    }
    DANodeGraphicsScene::mousePressEvent(mouseEvent);
}

void DAWorkFlowGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent)
{
    DANodeGraphicsScene::mouseReleaseEvent(mouseEvent);
}

#if DA_USE_QGRAPHICSOBJECT
void DAWorkFlowGraphicsScene::backgroundPixmapItemXChanged()
{
    if (!isEnableItemMoveWithBackground()) {
        _backgroundPixmapItemLastPos = _backgroundPixmapItem->pos();
        return;
    }
    QPointF newPos = _backgroundPixmapItem->pos();
    QPointF sub(newPos - _backgroundPixmapItemLastPos);
    //
    QList< QGraphicsItem* > itemsWithoutLink = getGraphicsItemsWithoutLink();

    for (QGraphicsItem* item : qAsConst(itemsWithoutLink)) {
        if (item == getBackgroundPixmapItem()) {
            // PixmapItem 也会获取到，避免递归
            continue;
        }
        if (nullptr != item->parentItem()) {
            continue;
        }
        QPointF tempPos = sub + item->pos();
        item->setPos(tempPos);
    }

    _backgroundPixmapItemLastPos = newPos;
}

void DAWorkFlowGraphicsScene::backgroundPixmapItemYChanged()
{
    if (!isEnableItemMoveWithBackground()) {
        _backgroundPixmapItemLastPos = _backgroundPixmapItem->pos();
        return;
    }
    QPointF newPos = _backgroundPixmapItem->pos();
    QPointF sub(newPos - _backgroundPixmapItemLastPos);
    QList< QGraphicsItem* > itemsWithoutLink = getGraphicsItemsWithoutLink();

    for (QGraphicsItem* item : qAsConst(itemsWithoutLink)) {
        if (item == getBackgroundPixmapItem()) {
            // PixmapItem 也会获取到，避免递归
            continue;
        }
        if (nullptr != item->parentItem()) {
            continue;
        }
        QPointF tempPos = sub + item->pos();
        item->setPos(tempPos);
    }
    _backgroundPixmapItemLastPos = newPos;
}

void DAWorkFlowGraphicsScene::backgroundPixmapItemBodyItemBodySizeChanged(const QSizeF& oldsize, const QSizeF& newsize)
{
    QPointF lastPost = _pixmapResizeLastPos;
    QPointF newPos   = _backgroundPixmapItem->pos();
    qDebug() << "oldPos=" << _backgroundPixmapItemLastPos << " newPos=" << newPos;
    qDebug() << "oldsize=" << oldsize << " newsize=" << newsize;

    //    QList< DAAbstractNodeGraphicsItem* > list = getNodeGraphicsItems();
    //    for (auto item : qAsConst(list)) {
    //        QPointF itemPos = item->pos();
    //        qDebug() << "itemPos=" << itemPos << " lastPost=" << _pixmapResizeLastPos;
    //        qreal xSub = 0;
    //        qreal ySub = 0;
    //        if (lastPost.x() < 0) {
    //            xSub = itemPos.x() + lastPost.x();
    //        } else {
    //            xSub = itemPos.x() - lastPost.x();
    //        }
    //        if (lastPost.x() < 0) {
    //            ySub = itemPos.y() + lastPost.y();
    //        } else {
    //            ySub = itemPos.y() - lastPost.y();
    //        }
    //        qreal dx = (xSub / oldsize.width()) * newsize.width();
    //        qreal dy = (ySub / oldsize.height()) * newsize.height();
    //        item->setPos(QPointF(dx, dy));
    //    }

    //    _pixmapResizeLastPos = newPos;
}
#endif
